package com.ssm.basis.service.support;

import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.boot.env.PropertiesPropertySourceLoader;
import org.springframework.boot.env.PropertySourceLoader;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.core.io.support.PropertySourceFactory;
import org.springframework.core.io.support.ResourcePropertySource;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.Objects;
import java.util.Optional;
import java.util.Properties;

/**
 * @see org.springframework.context.annotation.PropertySource 用于导入 .properties 的属性配置文件
 * @see org.springframework.context.annotation.ImportResource 用于导入 .xml 的 Bean 信息的配置文件
 * https://blog.csdn.net/f641385712/article/details/90636649
 * use @PropertySource(value = "classpath:xxx.yml", factory = ConfigSourceFactory.class) -> @Value("${xxx}")
 */
public class ConfigSourceFactory implements PropertySourceFactory {
    private static final PropertySourceLoader YAML_LOADER = new YamlPropertySourceLoader();
    private static final YamlPropertiesFactoryBean YAML_FACTORY = new YamlPropertiesFactoryBean();
    private static final PropertySourceLoader PROPERTIES_LOADER = new PropertiesPropertySourceLoader();

    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
        String resourceName = Optional.ofNullable(name).orElse(resource.getResource().getFilename());
        String filenameExtension = StringUtils.getFilenameExtension(resourceName);
        if (Objects.isNull(filenameExtension)) {
            return new ResourcePropertySource(resource);
        }
        switch (filenameExtension.toLowerCase()) {
            case "yml":
            case "yaml":
            case "json":
                // yaml 是 json 的超集，合法的 json 也是合法的 yaml，继承 YamlPropertySourceLoader，把 json 扩展名添加进去
                // YAML_FACTORY.setResources(resource.getResource());
                // YAML_FACTORY.afterPropertiesSet();
                // return new PropertiesPropertySource(resourceName, YAML_FACTORY.getObject());
                return YAML_LOADER.load(resourceName, resource.getResource()).get(0);
            case "xml":
            case "properties":
                return PROPERTIES_LOADER.load(resourceName, resource.getResource()).get(0);
            default:
                return new PropertiesPropertySource(resourceName, new Properties());
        }
    }
}
